package com.yifeng.repo.base.security.context.manager;

import com.gomcarter.frameworks.base.common.AssertUtils;
import com.yifeng.repo.base.constant.BaseConstant;
import com.yifeng.repo.base.dto.PermissionDto;
import com.yifeng.repo.base.dto.UserDto;
import com.yifeng.repo.base.security.auth.constant.SecurityTypeEnum;

import java.util.Optional;

/**
 * Created by daibing on 2023/8/23.
 */
public class RequestContextManager {
    private static final ThreadLocal<String> CTX_TOKEN = new ThreadLocal<>();
    private static final ThreadLocal<UserDto> CTX_USER = new ThreadLocal<>();
    private static final ThreadLocal<PermissionDto> CTX_PERMISSION = new ThreadLocal<>();
    private static final ThreadLocal<String> CTX_REQ_APP_ID = new ThreadLocal<>();
    private static final ThreadLocal<Long> CTX_REQ_START_TIME = new ThreadLocal<>();
    private static final ThreadLocal<SecurityTypeEnum> CTX_SECURITY_TYPE = new ThreadLocal<>();
    private static final ThreadLocal<Boolean> CTX_TRANSFER_RESP_DATA_KEY = new ThreadLocal<>();
    private static final ThreadLocal<String> CTX_SHARDING_STORE_CODE = new ThreadLocal<>();

    public static String getToken() {
        return CTX_TOKEN.get();
    }

    public static void setToken(String token) {
        CTX_TOKEN.set(token);
    }

    public static UserDto getUser() {
        return CTX_USER.get();
    }

    public static UserDto getUserIfPresent() {
        UserDto userDto = CTX_USER.get();
        AssertUtils.notNull(userDto, "userDto is null");
        return userDto;
    }

    public static UserDto getUserOrDefault() {
        return Optional.ofNullable(CTX_USER.get()).orElse(new UserDto(BaseConstant.EMPTY, BaseConstant.EMPTY));
    }
    public static UserDto getUserOrDefault(UserDto defaultUserDto) {
        return Optional.ofNullable(CTX_USER.get()).orElse(defaultUserDto);
    }

    public static void setUser(UserDto value) {
        CTX_USER.set(value);
    }

    public static PermissionDto getPermission() {
        return CTX_PERMISSION.get();
    }

    public static PermissionDto getPermissionOrDefault() {
        return Optional.ofNullable(CTX_PERMISSION.get()).orElse(new PermissionDto(BaseConstant.EMPTY, BaseConstant.EMPTY, BaseConstant.EMPTY, BaseConstant.EMPTY));
    }
    public static PermissionDto getPermissionOrDefault(PermissionDto defaultPermissionDto) {
        return Optional.ofNullable(CTX_PERMISSION.get()).orElse(defaultPermissionDto);
    }

    public static void setPermission(PermissionDto value) {
        CTX_PERMISSION.set(value);
    }

    public static String getReqAppId() {
        return CTX_REQ_APP_ID.get();
    }

    public static void setReqAppId(String reqAppId) {
        CTX_REQ_APP_ID.set(reqAppId);
    }

    public static Long getRequestStartTime() {
        return CTX_REQ_START_TIME.get();
    }

    public static void setRequestStartTime(Long requestStartTime) {
        CTX_REQ_START_TIME.set(requestStartTime);
    }

    public static SecurityTypeEnum getSecurityType() {
        return CTX_SECURITY_TYPE.get();
    }

    public static void setSecurityType(SecurityTypeEnum securityType) {
        CTX_SECURITY_TYPE.set(securityType);
    }

    /**
     * @deprecated Jackson自定义PropertyNamingStrategy使用需要特别谨慎，避免因为业务使用不当，Jackson缓存机制造成字段精简运行异常
     */
    public static Boolean getTransferRespDataKey() {
        return CTX_TRANSFER_RESP_DATA_KEY.get();
    }

    /**
     * @deprecated Jackson自定义PropertyNamingStrategy使用需要特别谨慎，避免因为业务使用不当，Jackson缓存机制造成字段精简运行异常
     */
    public static void setTransferRespDataKey(boolean transferRespDataKey) {
        CTX_TRANSFER_RESP_DATA_KEY.set(transferRespDataKey);
    }

    public static String getShardingStoreCode() {
        return CTX_SHARDING_STORE_CODE.get();
    }

    /**
     * 按省拆库中设置sharding门店编号，默认从请求url参数获取，如果未获取到就要求业务代码自己在controller层设置
     */
    public static void setShardingStoreCode(String storeCode) {
        CTX_SHARDING_STORE_CODE.set(storeCode);
    }

    public static void clear() {
        CTX_TOKEN.remove();
        CTX_USER.remove();
        CTX_PERMISSION.remove();
        CTX_REQ_APP_ID.remove();
        CTX_REQ_START_TIME.remove();
        CTX_SECURITY_TYPE.remove();
        CTX_TRANSFER_RESP_DATA_KEY.remove();
        CTX_SHARDING_STORE_CODE.remove();
    }
}
